using System;
using Core.Domain.Entities;

namespace Core.Domain.Enums
{
  ///<summary>Age group</summary>
  public class AgeGroup : BaseEnumeration<AgeGroup, string>
  {
    ///<summary>Represents an Adult, age 21+</summary>
    public static readonly AgeGroup Adult = new AgeGroup("A", "Adult", 21, int.MaxValue);

    ///<summary>Represents an Child, age 0 - 11</summary>
    public static readonly AgeGroup Child = new AgeGroup("C", "Child", 0, 11);

    ///<summary>Represents an Junior Youth, age 12 - 14</summary>
    public static readonly AgeGroup JuniorYouth = new AgeGroup("JY", "Junior Youth", 12, 14);

    ///<summary>Age group is unknown!</summary>
    public static readonly AgeGroup Unknown = new AgeGroup("?", "Unknown", int.MaxValue, int.MinValue);

    ///<summary>Represents an Youth, age 15 - 20</summary>
    public static readonly AgeGroup Youth = new AgeGroup("Y", "Youth", 15, 20);

    private readonly string _displayName;
    private int _maxAge;
    private int _minAge;

    static AgeGroup()
    {
      Add(Adult);
      Add(Youth);
      Add(JuniorYouth);
      Add(Child);
    }

    private AgeGroup(string internalValue, string displayName, int minAge, int maxAge) : base(internalValue, displayName)
    {
      _minAge = minAge;
      _maxAge = maxAge;
    }

    ///<summary>Minimum age for this group</summary>
    public int MinAge
    {
      get { return _minAge; }
    }

    ///<summary>Maximum age for this group</summary>
    public int MaxAge
    {
      get { return _maxAge; }
    }

    public AgeGroup Parse(string value)
    {
      switch (value.ToLower())
      {
        case "child":
        case "c":
          return Child;

        case "adult":
        case "a":
          return Adult;

        case "jnryouth":
        case "junioryouth":
        case "junior youth":
        case "preyouth":
        case "jy":
          return JuniorYouth;

        case "y":
        case "youth":
          return Youth;
      }
      return Unknown;
    }

    ///<summary>Determine age group base on a date
    ///</summary>
    ///<param name="person"></param>
    ///<param name="asOfDate"></param>
    ///<returns></returns>
    public static AgeGroup DetermineAgeGroup(Person person)
    {
      return DetermineAgeGroup(person, DateTime.Today);
    }

    ///<summary>Determine age group</summary>
    ///<param name="birthDate"></param>
    ///<param name="asOfDate"></param>
    ///<returns></returns>
    public static AgeGroup DetermineAgeGroup(DateTime birthDate)
    {
      return DetermineAgeGroup(birthDate, DateTime.Today);
    }

    ///<summary>Determine age group</summary>
    ///<param name="birthDate"></param>
    ///<param name="asOfDate"></param>
    ///<returns></returns>
    public static AgeGroup DetermineAgeGroup(DateTime birthDate, DateTime asOfDate)
    {
      if (birthDate == DateTime.MinValue)
      {
        // no DOB entered, assume adult
        return Adult;
      }

      var age = birthDate.AgeAt(asOfDate);

      if (age >= 21)
      {
        return Adult;
      }
      if (age >= 15)
      {
        return Youth;
      }
      if (age >= 12)
      {
        return JuniorYouth;
      }
      return Child;
    }


    ///<summary>Determine age group base on a date
    ///</summary>
    ///<param name="person"></param>
    ///<param name="asOfDate"></param>
    ///<returns></returns>
    public static AgeGroup DetermineAgeGroup(Person person, DateTime asOfDate)
    {
      if (person == null)
      {
        return Unknown;
      }

      return DetermineAgeGroup(person.BirthDate, asOfDate);
    }
  }
}